[IA64] Support Xen/IA64 self-grant-table-page-mapping.
authorawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Fri, 10 Nov 2006 18:44:38 +0000 (11:44 -0700)
committerawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Fri, 10 Nov 2006 18:44:38 +0000 (11:44 -0700)
Before the changeset 10677:2937703f0ed0 of xen-unstable.hg,
it is prohibited mapping a page which is granted by self domain.
However it is allowed in order to mount blktap image by dom0.
This patch is necessary to support blktap on Xen/IA64.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
xen/arch/ia64/xen/mm.c
xen/include/asm-ia64/linux-xen/asm/pgtable.h
xen/include/public/arch-ia64.h

index 653425cf5efd57c4905285021b25bfb9151a141f..8cc3d3f53708db3e558dfa52909c41f6663fbd1a 100644 (file)
@@ -765,7 +765,8 @@ __assign_new_domain_page(struct domain *d, unsigned long mpaddr, pte_t* pte)
     // because set_pte_rel() has release semantics
     set_pte_rel(pte,
                 pfn_pte(maddr >> PAGE_SHIFT,
-                        __pgprot(__DIRTY_BITS | _PAGE_PL_2 | _PAGE_AR_RWX)));
+                        __pgprot(_PAGE_PGC_ALLOCATED | __DIRTY_BITS |
+                                 _PAGE_PL_2 | _PAGE_AR_RWX)));
 
     smp_mb();
     return p;
@@ -807,6 +808,7 @@ flags_to_prot (unsigned long flags)
 #ifdef CONFIG_XEN_IA64_TLB_TRACK
     res |= flags & ASSIGN_tlb_track ? _PAGE_TLB_TRACKING: 0;
 #endif
+    res |= flags & ASSIGN_pgc_allocated ? _PAGE_PGC_ALLOCATED: 0;
     
     return res;
 }
@@ -866,7 +868,8 @@ assign_domain_page(struct domain *d,
     set_gpfn_from_mfn(physaddr >> PAGE_SHIFT, mpaddr >> PAGE_SHIFT);
     // because __assign_domain_page() uses set_pte_rel() which has
     // release semantics, smp_mb() isn't needed.
-    (void)__assign_domain_page(d, mpaddr, physaddr, ASSIGN_writable);
+    (void)__assign_domain_page(d, mpaddr, physaddr,
+                               ASSIGN_writable | ASSIGN_pgc_allocated);
 }
 
 int
@@ -1035,6 +1038,7 @@ assign_domain_mach_page(struct domain *d,
                         unsigned long mpaddr, unsigned long size,
                         unsigned long flags)
 {
+    BUG_ON(flags & ASSIGN_pgc_allocated);
     assign_domain_same_page(d, mpaddr, size, flags);
     return mpaddr;
 }
@@ -1046,15 +1050,17 @@ domain_put_page(struct domain* d, unsigned long mpaddr,
     unsigned long mfn = pte_pfn(old_pte);
     struct page_info* page = mfn_to_page(mfn);
 
-    if (page_get_owner(page) == d ||
-        page_get_owner(page) == NULL) {
-        BUG_ON(get_gpfn_from_mfn(mfn) != (mpaddr >> PAGE_SHIFT));
-        set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY);
-    }
-
-    if (clear_PGC_allocate)
-        try_to_clear_PGC_allocate(d, page);
+    if (pte_pgc_allocated(old_pte)) {
+        if (page_get_owner(page) == d || page_get_owner(page) == NULL) {
+            BUG_ON(get_gpfn_from_mfn(mfn) != (mpaddr >> PAGE_SHIFT));
+           set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY);
+        } else {
+            BUG();
+        }
 
+       if (clear_PGC_allocate)
+            try_to_clear_PGC_allocate(d, page);
+    }
     domain_page_flush_and_put(d, mpaddr, ptep, old_pte, page);
 }
 
@@ -1146,6 +1152,7 @@ assign_domain_page_cmpxchg_rel(struct domain* d, unsigned long mpaddr,
     }
 
     BUG_ON(!pte_mem(old_pte));
+    BUG_ON(!pte_pgc_allocated(old_pte));
     BUG_ON(page_get_owner(old_page) != d);
     BUG_ON(get_gpfn_from_mfn(old_mfn) != (mpaddr >> PAGE_SHIFT));
     BUG_ON(old_mfn == new_mfn);
@@ -1240,7 +1247,7 @@ dom0vp_add_physmap(struct domain* d, unsigned long gpfn, unsigned long mfn,
     struct domain* rd;
 
     /* Not allowed by a domain.  */
-    if (flags & ASSIGN_nocache)
+    if (flags & (ASSIGN_nocache | ASSIGN_pgc_allocated))
         return -EINVAL;
 
     rd = find_domain_by_id(domid);
@@ -1424,8 +1431,6 @@ create_grant_host_mapping(unsigned long gpaddr,
     page = mfn_to_page(mfn);
     ret = get_page(page, page_get_owner(page));
     BUG_ON(ret == 0);
-    BUG_ON(page_get_owner(mfn_to_page(mfn)) == d &&
-           get_gpfn_from_mfn(mfn) != INVALID_M2P_ENTRY);
     assign_domain_page_replace(d, gpaddr, mfn,
 #ifdef CONFIG_XEN_IA64_TLB_TRACK
                                ASSIGN_tlb_track |
@@ -1551,7 +1556,8 @@ steal_page(struct domain *d, struct page_info *page, unsigned int memflags)
         // has release semantics.
 
         ret = assign_domain_page_cmpxchg_rel(d, gpfn << PAGE_SHIFT, page, new,
-                                             ASSIGN_writable);
+                                             ASSIGN_writable |
+                                             ASSIGN_pgc_allocated);
         if (ret < 0) {
             gdprintk(XENLOG_INFO, "assign_domain_page_cmpxchg_rel failed %d\n",
                     ret);
@@ -1648,7 +1654,8 @@ guest_physmap_add_page(struct domain *d, unsigned long gpfn,
     BUG_ON(ret == 0);
     set_gpfn_from_mfn(mfn, gpfn);
     smp_mb();
-    assign_domain_page_replace(d, gpfn << PAGE_SHIFT, mfn, ASSIGN_writable);
+    assign_domain_page_replace(d, gpfn << PAGE_SHIFT, mfn,
+                               ASSIGN_writable | ASSIGN_pgc_allocated);
 
     //BUG_ON(mfn != ((lookup_domain_mpa(d, gpfn << PAGE_SHIFT) & _PFN_MASK) >> PAGE_SHIFT));
 
index 7b23205f8507ee86994028751384f22ccf4c9ce2..a859a8b4372b97c8c58928ee3e9d50adacb4c5a9 100644 (file)
@@ -89,6 +89,8 @@
     ((pte_val(pte) & _PAGE_TLB_INSERTED_MANY) != 0)
 #endif // CONFIG_XEN_IA64_TLB_TRACK
 
+#define _PAGE_PGC_ALLOCATED_BIT        59      /* _PGC_allocated */
+#define _PAGE_PGC_ALLOCATED    (__IA64_UL(1) << _PAGE_PGC_ALLOCATED_BIT)
 /* domVTI */
 #define GPFN_MEM               (0UL << 60)     /* Guest pfn is normal mem */
 #define GPFN_FRAME_BUFFER      (1UL << 60)     /* VGA framebuffer */
@@ -333,6 +335,7 @@ set_pte_rel(volatile pte_t* ptep, pte_t pteval)
 #define pte_young(pte)         ((pte_val(pte) & _PAGE_A) != 0)
 #define pte_file(pte)          ((pte_val(pte) & _PAGE_FILE) != 0)
 #ifdef XEN
+#define pte_pgc_allocated(pte) ((pte_val(pte) & _PAGE_PGC_ALLOCATED) != 0)
 #define pte_mem(pte) \
        (!(pte_val(pte) & (GPFN_IO_MASK | GPFN_INV_MASK)) && !pte_none(pte))
 #endif
index 01fb5f2ec80368e054e53261a20fa7a3a6571ead..01f6362d82e6219af6b419bbbfd64915c335b95b 100644 (file)
@@ -384,6 +384,9 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
 // tlb tracking
 #define _ASSIGN_tlb_track               2
 #define ASSIGN_tlb_track                (1UL << _ASSIGN_tlb_track)
+/* Internal only: associated with PGC_allocated bit */
+#define _ASSIGN_pgc_allocated           3
+#define ASSIGN_pgc_allocated            (1UL << _ASSIGN_pgc_allocated)
 
 /* This structure has the same layout of struct ia64_boot_param, defined in
    <asm/system.h>.  It is redefined here to ease use.  */